package com.zhiyizhen.callnumber.net;

import android.content.ContentResolver;
import android.net.Uri;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.zhiyizhen.callnumber.common.LogUtil;
import com.zhiyizhen.callnumber.net.response.ProgressResponseBody;
import com.zhiyizhen.callnumber.net.util.FileIOUtil;
import com.zhiyizhen.callnumber.net.util.NetworkUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 下载器
 */
public class Downloader {

    public interface DownloadListener {

        void onProgress(int progress);

        void onDownloadFinished(Uri uri);

        void onDownloadFailed(String error);

    }

    public static void download(final String url, final Uri destUri, final DownloadListener listener) {
        final ProgressResponseBody.ProgressListener progressListener = (bytesRead, contentLength, done) -> {
            if (listener != null) {
                listener.onProgress((int) (bytesRead * 100 / contentLength));
            }
        };

        OkHttpClient client = new OkHttpClient.Builder()
                .addNetworkInterceptor(new Interceptor() {
                    @Override
                    @NonNull
                    public Response intercept(@NonNull Chain chain) throws IOException {
                        Response originalResponse = chain.proceed(chain.request());
                        return originalResponse.newBuilder()
                                .body(new ProgressResponseBody(originalResponse, progressListener))
                                .build();
                    }
                })
                .build();

        Request request = new Request.Builder()
                .url(url)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                if (listener != null) {
                    listener.onDownloadFailed("下载失败！");
                }
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) {
                response(destUri, listener, response);

            }
        });
    }

    private static void response(Uri destUri, final DownloadListener listener, @NonNull Response response) {
        if (listener == null) {
            return;
        }
        boolean success = false;
        final String scheme = destUri.getScheme();
        if (!TextUtils.isEmpty(scheme) && response.body() != null) {
            if (scheme.equals("file")) {
                success = FileIOUtil.writeFileFromIS(destUri.getPath(), response.body().byteStream());
            } else if (scheme.equals("content")) {
                success = writeStreamToUri(response.body().byteStream(), destUri);
            }
        }

        if (success) {
            listener.onDownloadFinished(destUri);
        } else {
            listener.onDownloadFailed("保存文件失败！");
        }
    }

    private static boolean writeStreamToUri(final InputStream is, Uri uri) {
        ContentResolver resolver = NetworkUtils.getContext().getContentResolver();
        OutputStream os = null;
        try {
            os = resolver.openOutputStream(uri);
            if (os == null) {
                return false;
            }

            byte[] data = new byte[1024];
            int len;
            while ((len = is.read(data)) != -1) {
                os.write(data, 0, len);
            }
            return true;
        } catch (IOException e) {
            LogUtil.e(e);
            return false;
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                LogUtil.e(e);
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                LogUtil.e(e);
            }
        }
    }

}
